﻿using System;
using System.Collections.Generic;
using System.IO;
using GestureMatching.DataStructure;

namespace GestureMatching
{
    public class GestureRecordManager
    {
        public static readonly string KEY_GESTURE = "gesture";
        public static readonly string KEY_GESTURE_NAME = "gesture_name";
        public static readonly string KEY_GESTURE_MEANING = "gesture_meaning";
        private static readonly GestureRecordManager gestureRecordManager = new GestureRecordManager();
        private LinkedList<Dictionary<String, Object>> allGestureRecord;
        private String filePath = null;

        public GestureRecordManager()
            : this("FILE_PATH")
        {
        }

        public GestureRecordManager(String filePath)
        {
            this.filePath = filePath;
            Update();
        }

        public static GestureRecordManager Me()
        {
            return gestureRecordManager;
        }

        public String GetFilePath()
        {
            return filePath;
        }

        public void AddGestureRecord(Dictionary<String, Object> gestureRecord)
        {
            foreach (Dictionary<String, Object> tempGestureRecord in allGestureRecord)
            {
                if (tempGestureRecord[KEY_GESTURE_NAME].Equals(gestureRecord[KEY_GESTURE_NAME]))
                {
                    allGestureRecord.Remove(tempGestureRecord);
                }
            }
            allGestureRecord.AddFirst(gestureRecord);
            WriteAllGestureRecord(filePath, allGestureRecord);
        }

        public void DeleteGestureRecord(Dictionary<String, Object> gestureRecord)
        {
            foreach (Dictionary<String, Object> tempGestureRecord in allGestureRecord)
            {
                if (tempGestureRecord[KEY_GESTURE_NAME].Equals(gestureRecord[KEY_GESTURE_NAME]))
                {
                    allGestureRecord.Remove(tempGestureRecord);
                }
            }
            WriteAllGestureRecord(filePath, allGestureRecord);
        }

        public Dictionary<String, Object> GetGestureRecord(String gestureJson)
        {
            //TODO:Change these ugly code;

            Dictionary<String, Object> gestureRecord = new Dictionary<string, object>();

            Char[] splitSymbol = { '[', ']' };
            String[] splitResults = gestureJson.Substring(1, gestureJson.Length - 2).Split(splitSymbol);
            splitResults[0] += splitResults[2];

            splitSymbol = new Char[] { '{', };
            String[] secondSplitResults = splitResults[1].Split(splitSymbol);
            TimingQueue tempTimingQueue = new TimingQueue();
            splitSymbol = new Char[] { ':', '}', '\"', ',' };
            foreach (String secondSplitResult in secondSplitResults)
            {
                TimingNode tempTimingNode = new TimingNode();
                tempTimingNode.data.X = float.Parse((secondSplitResult.Split(splitSymbol))[1]);
                tempTimingNode.data.Y = float.Parse((secondSplitResult.Split(splitSymbol))[3]);
                tempTimingNode.data.Z = float.Parse((secondSplitResult.Split(splitSymbol))[5]);
                tempTimingNode.createTime = DateTime.Parse((secondSplitResult.Split(splitSymbol))[7]);

                tempTimingQueue.Push(tempTimingNode);
            }
            gestureRecord.Add(KEY_GESTURE, tempTimingQueue);

            splitSymbol = new Char[] { ',' };
            splitResults = splitResults[0].Split(splitSymbol);
            splitSymbol = new Char[] { '\"', ':' };
            gestureRecord.Add(KEY_GESTURE_NAME, (splitResults[0].Split(splitSymbol))[1]);
            gestureRecord.Add(KEY_GESTURE_MEANING, (splitResults[2].Split(splitSymbol))[1]);

            return gestureRecord;
        }

        public String GetGestureJson(Dictionary<String, Object> gestureRecord)
        {
            String gestureJson =
                  "{"
                + Tool.Stringify(KEY_GESTURE_NAME, gestureRecord[KEY_GESTURE_NAME]) + ","
                + Tool.Stringify(KEY_GESTURE, gestureRecord[KEY_GESTURE]) + ","
                + Tool.Stringify(KEY_GESTURE_MEANING, gestureRecord[KEY_GESTURE_MEANING])
                + "}";

            return gestureJson;
        }

        public LinkedList<Dictionary<String, Object>> ReadAllGestureJson(StreamReader streamReader)
        {
            LinkedList<Dictionary<String, Object>> gestureRecords = new LinkedList<Dictionary<string, object>>();

            String tempGestureJson;
            Dictionary<String, Object> tempGestureRecord;
            while ((tempGestureJson = streamReader.ReadLine()) != null)
            {
                Console.WriteLine(tempGestureJson);
                tempGestureRecord = GestureRecordManager.Me().GetGestureRecord(tempGestureJson);
                gestureRecords.AddFirst(tempGestureRecord);
            }
            Console.WriteLine("The end of the stream has been reached.");

            return gestureRecords;
        }

        public void WriteAllGestureRecord(StreamWriter streamWriter, LinkedList<Dictionary<String, Object>> allGestureRecord)
        {
            String tempGestureJson;
            foreach (Dictionary<String, Object> tempGestureRecord in allGestureRecord)
            {
                tempGestureJson = GetGestureJson(tempGestureRecord);
                streamWriter.WriteLine(tempGestureJson);
            }

            Console.WriteLine("The end of the allGestureRecord has been writed.");
        }

        public LinkedList<Dictionary<String, Object>> ReadAllGestureJson(String filePath)
        {
            LinkedList<Dictionary<String, Object>> gestureRecords = null;

            if (!File.Exists(filePath))
            {
                Console.WriteLine("{0} does not exist.", filePath);
                return gestureRecords;
            }
            using (StreamReader streamReader = File.OpenText(filePath))
            {
                gestureRecords = ReadAllGestureJson(streamReader);
            }

            return gestureRecords;
        }

        public void WriteAllGestureRecord(String filePath, LinkedList<Dictionary<String, Object>> allGestureRecord)
        {
            using (StreamWriter streamWriter = File.CreateText(filePath))
            {
                WriteAllGestureRecord(streamWriter, allGestureRecord);
            }
        }

        public LinkedList<Dictionary<String, Object>> GetAllGestureRecord()
        {
            return allGestureRecord;
        }

        public void Update()
        {
            allGestureRecord = ReadAllGestureJson(filePath);
        }
    }
}